package utils;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Vector;

/**
 * Parses native Java Objects into String values. String, Vector, Double, Integer, etc.
 * It would be possible to parse third-party Objects, as long as you create a new parse method for them.
 * @date Mar 14, 2011
 * @author Eric Kisner
 */
public class ObjectParser {

    /**
     * This method will take a list of return types, and values to be passed into methods of this class. Each method
     * of this class has the same convention: String parseTYPE( Object val ), so we can use reflection to invoke
     * these methods if we have the 'TYPE' that we want to parse from 'val'.
     *
     * To use this method, the return types and return values must match up exactly. For example, to parse data from a
     * Vector and a Double (in that order):
     * returnTypes = { "Vector", "Double" };
     * returnValues = { Vector Object, Double Object };
     * This will run the parseVector and parseDouble methods using the parameter returnValues.get(0)
     * and returnValues.get(1), respectively.
     *
     * @param returnTypes A list of return types we want to parse. Must be a native Java Object String, and cannot be
     *                    a primitive type. Ex: "Double", "String", "Vector"
     * @param returnValues A list of values that we want to parse. Must be a list of native Java Objects.
     * 
     * @return A list of Strings that we have parsed from returnValues, or an empty list if there was an error.
     */
    public static List<String> runParseObjectMethods( List<String> returnTypes, List<Object> returnValues ) {
        List<String> ret = new ArrayList<String>();
        Method[] methods = ObjectParser.class.getMethods();
        for( int j = 0; j < returnTypes.size(); j++ ) {
            for( int i = 0; i < methods.length; i++ ) {
                Method method = methods[i];
                if( method.getName().equalsIgnoreCase( "parse" + returnTypes.get( j ) ) ) {
                    try {
                        ret.add( (String) method.invoke( null, returnValues.get( j ) ) );
                        continue;
                    } catch( Exception e ) {
                        //This will most likely never happen, since the parse methods have identical conventions,
                        //which means it would only not run if this method is used incorrectly, or any of the methods
                        //are moved.
                        ExceptionUtils.handleException( e, ObjectParser.class );
                        return Collections.emptyList();
                    }
                }
            }
        }
        return ret;
    }

    public static String parseVector( Object val ) {
        String ret = "";
        for( Object obj : (Vector) val ) {
            //Add a delimiter so we can further parse the vector into separate strings later.
            ret += obj.toString() + ";";
        }
        //Trim the last '~' from the string before returning.
        return ret.substring( 0, ret.length() - 1 );
    }

    public static String parseString( Object val ) {
        return val.toString();
    }

    public static String parseDouble( Object val ) {
        return val.toString();
    }
}
